package com.gitee.apanlh.util.reflection.load;

import com.gitee.apanlh.annotation.load.InitLoadClass;
import com.gitee.apanlh.exp.InitLoadException;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.SingletonUtils;
import com.gitee.apanlh.util.log.Log;
import com.gitee.apanlh.util.reflection.ClassUtils;
import com.gitee.apanlh.util.reflection.ReflectionUtils;

import java.util.List;

/**	
 * 	初始化加载类
 * 	#mark 与InitLoadClassBean+RedisLoadTask加载时会出现问题
 * 	@author Pan
 */
public class InitLoadClassBean extends ClassLoader {
	
	/**
	 * 	默认构造函数
	 * 	
	 * 	@author Pan
	 */
	public InitLoadClassBean() {
		super();
	}
	
	/**	
	 * 	构造函数
	 * 	<br>自定义包范围，返回的是指定包范围下的所有Class
	 * 	<br>例如:{@code com.xxx.xxx}
	 * 	<br>多层级
	 * 	
	 * 	@author Pan
	 * 	@param 	packagePaths	多层级目录
	 */
	public InitLoadClassBean(String... packagePaths) {
		try {
			for (String packagePath : packagePaths) {
				List<Class<?>> list = ClassUtils.getPackageClasses(packagePath);
				
				IteratorUtils.collection(list, (clazz, iterator) -> {
					InitLoadClass initLoadAnnotation = (InitLoadClass) ReflectionUtils.getClassAnnotation(clazz, InitLoadClass.class);
					if (initLoadAnnotation != null) {
						Class<?> loadClass = ClassUtils.load(clazz.getName());
						Log.get().info("[{}] static loading completed", ClassUtils.getSimpleName(clazz));
						boolean initInstance = initLoadAnnotation.initInstance();
						boolean initSingleton = false;
						if (initInstance) {
							//	不存放单例
							if (!initLoadAnnotation.initSingleton()) {
								ReflectionUtils.newInstance(loadClass);
							} else {
								initSingleton = true;
								SingletonUtils.get(loadClass);
							}
							Log.get().info("[{}] init class[{}], singleton[{}]", ClassUtils.getSimpleName(clazz), initInstance, initSingleton);
						}
					}
				});
			}
		} catch (Exception e) {
			throw new InitLoadException(e.getMessage(), e);
		}
	}
	
	@Override
	protected final Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
		return super.loadClass(name, resolve);
	}
}
